/*
 * Copyright (c) 2023 CompanyNameMagicTag.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "mainView.h"
#include "events.h"

namespace OHOS {
class AnalogClockCallback : public AnimatorCallback {
public:
    explicit AnalogClockCallback(UIAnalogClock* clock) : clock_(clock) {}
    ~AnalogClockCallback() {};
    virtual void Callback(UIView* view)
    {
        count_++;
        if ((count_ == 30) && (clock_ != nullptr)) { // 30: run every tick (~30ms)
            clock_->IncOneSecond();
            count_ = 0;
        }
    }
private:
    UIAnalogClock* clock_;
    int16_t count_ = 0;
};
class SweepClockCallback : public AnimatorCallback {
public:
    explicit SweepClockCallback(UISweepClock *clock) : sweepClock(clock) {}
    ~SweepClockCallback() {}

    virtual void Callback(UIView *view)
    {
        //UNUSED(view);
        struct timeval tv;
        gettimeofday(&tv, NULL);
        uint64_t second = tv.tv_sec;
        uint64_t uSecond = tv.tv_usec;
        uint64_t minute = second / MIN_TO_HOUR;
        uint64_t hour = minute / MIN_TO_HOUR;
        uint8_t realHour = static_cast<uint8_t>(hour % HOURLY_SYSTEM);
        uint8_t realMinute = static_cast<uint8_t>(minute % MIN_TO_HOUR);
        uint16_t realMilliSecond = static_cast<uint16_t>((second % MIN_TO_HOUR) *
            SEC_TO_MILLI + uSecond / USEC_TO_MILLI);
        sweepClock->SetSweepTime12Hour(realHour, realMinute, realMilliSecond, 1);
    }

private:
    static constexpr int16_t SEC_TO_MILLI = 1000;
    static constexpr int16_t USEC_TO_MILLI = 1000;
    static constexpr int16_t MIN_TO_HOUR = 60;
    static constexpr int16_t HOURLY_SYSTEM = 24;
    static constexpr int16_t INTERVAL = 30;
    UISweepClock *sweepClock{nullptr};
};

void MainView::Init()
{
    if (container_ == nullptr) {
        container_ = new UIViewGroup();
        container_->SetPosition(0, 0, 466, 466);
        container_->SetStyle(STYLE_BACKGROUND_OPA, 0);
    }
    
    // Add RadioButton to App
    if (radioButton1_ == nullptr) {
        radioButton1_ = new UIRadioButton();
    }
    radioButton1_->SetPosition(100, 100);         // widget's left position and top position
    radioButton1_->Resize(50, 50);          // widget's width and height
    radioButton1_->SetViewId("radioButton1");// Set style

    // Set additional property
    radioButton1_->SetState(UICheckBox::SELECTED);
    radioButton1_->SetName("radioButton");

    // Add to rootView
    container_->Add(radioButton1_);
    radioButton1_->SetVisible(true);
    
    // Add Button to App
    if (button1_ == nullptr) {
        button1_ = new UIButton();
    }
    button1_->SetPosition(100, 100);         // widget's left position and top position
    button1_->Resize(180, 80);          // widget's width and height
    button1_->SetViewId("button1");// Set style

    // Set additional property
    button1_->SetStyleForState(STYLE_BORDER_COLOR, 0xff0b1928, UIButton::PRESSED);

    // Add to rootView
    container_->Add(button1_);
    button1_->SetVisible(true);
    
    // Add Chart to App
    if (uiChart1_ == nullptr) {
        uiChart1_ = new UIChartPolyline();
    }
    uiChart1_->SetPosition(100, 100);         // widget's left position and top position
    uiChart1_->Resize(200, 100);          // widget's width and height
    uiChart1_->SetViewId("uiChart1");// Set style
    uiChart1_->SetStyle(STYLE_BACKGROUND_OPA, 0x00);

    // Set additional property
    UIXAxis& uiChart1XAxis = uiChart1_->GetXAxis();
    UIYAxis& uiChart1YAxis = uiChart1_->GetYAxis();
    uiChart1XAxis.SetMarkNum(1);
    uiChart1XAxis.SetDataRange(0, 5);
    uiChart1XAxis.SetLineColor(Color::GetColorFromRGBA(0xff, 0xff, 0xff, 0xff));   
    uiChart1YAxis.SetMarkNum(1);
    uiChart1YAxis.SetDataRange(0, 300);
    uiChart1YAxis.SetLineColor(Color::GetColorFromRGBA(0xff, 0xff, 0xff, 0xff));
    UIChartDataSerial* uiChart1data1 = new UIChartDataSerial();
    uiChart1data1->SetMaxDataCount(3);
    Point uiChart1PointArray1[3] = { {0,150},{1,250},{2,170} };
    uiChart1data1->AddPoints(uiChart1PointArray1, 3);
    uiChart1data1->SetFillColor(Color::GetColorFromRGBA(0xff, 0xff, 0xff, 0xff));
    uiChart1data1->SetLineColor(Color::GetColorFromRGBA(0xff, 0xff, 0xff, 0xff));
    uiChart1data1->EnableGradient(false);
    uiChart1_->AddDataSerial(uiChart1data1);
    uiChart1_->SetGradientOpacity(0, 0);

    // Add to rootView
    container_->Add(uiChart1_);
    uiChart1_->SetVisible(true);
    
    // Add List to App
    if (list1_ == nullptr) {
        list1_ = new UIList();
    }
    list1_->SetPosition(100, 100);         // widget's left position and top position
    list1_->Resize(200, 60);          // widget's width and height
    list1_->SetViewId("list1");// Set style
    list1_->SetStyle(STYLE_BACKGROUND_COLOR, 0xff000000);

    // Set additional property

    if (list1data_ == nullptr) {
      list1data_ = new List<IconItemNode*>();  
    }
    if (list1adapter_ == nullptr) {
        list1adapter_ = new IconAdapter();
    }
    list1adapter_->SetData(list1data_);
    list1_->SetAdapter(list1adapter_);

    // Add to rootView
    container_->Add(list1_);
    list1_->SetVisible(true);
    
    // Add DigitalClock to App
    if (digitalClock1_ == nullptr) {
    digitalClock1_ = new UIDigitalClock();
    }
    digitalClock1_->SetPosition(100, 100);         // widget's left position and top position
    digitalClock1_->Resize(150, 100);          // widget's width and height
    digitalClock1_->SetViewId("digitalClock1");// Set style
    digitalClock1_->SetStyle(STYLE_BACKGROUND_COLOR, 0xffffffff);
    digitalClock1_->SetStyle(STYLE_BACKGROUND_OPA, 0xff);

    // Set additional property
    digitalClock1_->SetColor(Color::GetColorFromRGBA(0xff, 0x00, 0x00, 0xff));
    digitalClock1_->SetTime24Hour(0, 0, 0);

    // Add to rootView
    container_->Add(digitalClock1_);
    digitalClock1_->SetVisible(true);
    
    // Add Slider to App
    if (slider1_ == nullptr) {
        slider1_ = new UISlider();
    }
    slider1_->SetPosition(100, 100);         // widget's left position and top position
    slider1_->Resize(100, 30);          // widget's width and height
    slider1_->SetViewId("slider1");// Set style
    slider1_->SetStyle(STYLE_BACKGROUND_COLOR, 0xffffffff);
    slider1_->SetStyle(STYLE_BACKGROUND_OPA, 0xff);

    // Set additional property
    slider1_->SetValidWidth(100);
    slider1_->SetValidHeight(30);
    slider1_->SetValue(20);
    slider1_->SetSliderColor(Color::GetColorFromRGBA(0xff, 0xff, 0xff, 0xff), Color::GetColorFromRGBA(0x00, 0x00, 0x00, 0xff));
    slider1_->SetKnobWidth(30);
    slider1_->SetKnobStyle(STYLE_BACKGROUND_COLOR, 0xff808080);
    slider1_->SetForegroundStyle(STYLE_BACKGROUND_OPA, 0xff);

    // Add to rootView
    container_->Add(slider1_);
    slider1_->SetVisible(true);
    
    // Add ImageView to App
    if (image2_ == nullptr) {
        image2_ = new UIImageView();
    }
    image2_->SetPosition(100, 100);         // widget's left position and top position
    image2_->Resize(100, 100);          // widget's width and height
    image2_->SetViewId("image2");// Set style

    // Set additional property
#ifdef _WIN32
    char* image2imagesPath = "c:/Users/caiking/project/image_converter_tool/clock.bin";
#else
    char* image2imagesPath = "/user/res/clock.bin";
#endif
    image2_->SetSrc(image2imagesPath);

    // Add to rootView
    container_->Add(image2_);
    image2_->SetVisible(true);
    
    // Add AnalogClock to App
    if (analogClock1_ == nullptr) {
    analogClock1_ = new UIAnalogClock();
    }
    analogClock1_->SetPosition(-89, 71);         // widget's left position and top position
    analogClock1_->Resize(466, 466);          // widget's width and height
    analogClock1_->SetViewId("analogClock1");// Set style
    analogClock1_->SetStyle(STYLE_BACKGROUND_COLOR, 0xff000000);
    analogClock1_->SetStyle(STYLE_BACKGROUND_OPA, 0x00);

    // Set additional property
    analogClock1_->SetWorkMode(UIAnalogClock::WorkMode::NORMAL);
    analogClock1_->SetHandLine(UIAnalogClock::HandType::HOUR_HAND, { 233, 101 }, { 0, 132 }, Color::GetColorFromRGBA(0xff, 0xff, 0xff, 0xff), 5, 132, 255);
    analogClock1_->SetHandLine(UIAnalogClock::HandType::MINUTE_HAND, { 233, 56 }, { 0, 177 }, Color::GetColorFromRGBA(0x00, 0xff, 0x00, 0xff), 3, 177, 255);
    analogClock1_->SetHandLine(UIAnalogClock::HandType::SECOND_HAND, { 233, 10 }, { 0, 223 }, Color::GetColorFromRGBA(0xff, 0x00, 0x00, 0xff), 1, 223, 255);
    analogClock1_->SetTime12Hour(10, 20, 40, true);

    analogClock1callback_ = new AnalogClockCallback(analogClock1_);
    analogClock1animator_ = new Animator(analogClock1callback_, analogClock1_, 0, true);
    analogClock1animator_->Start();

    // Add to rootView
    container_->Add(analogClock1_);
    analogClock1_->SetVisible(true);
    
    // Add SweepClock to App
    if (sweepClock1_ == nullptr) {
    sweepClock1_ = new UISweepClock();
    }
    sweepClock1_->SetPosition(130, 111);         // widget's left position and top position
    sweepClock1_->Resize(466, 466);          // widget's width and height
    sweepClock1_->SetViewId("sweepClock1");// Set style
    sweepClock1_->SetStyle(STYLE_BACKGROUND_COLOR, 0xff000000);
    sweepClock1_->SetStyle(STYLE_BACKGROUND_OPA, 0x00);

    // Set additional property
    sweepClock1_->SetWorkMode(UISweepClock::WorkMode::NORMAL);
    sweepClock1_->SetHandLine(UISweepClock::HandType::HOUR_HAND, { 233, 101 }, { 0, 132 }, Color::GetColorFromRGBA(0xff, 0xff, 0xff, 0xff), 5, 132, 255);
    sweepClock1_->SetHandLine(UISweepClock::HandType::MINUTE_HAND, { 233, 56 }, { 0, 177 }, Color::GetColorFromRGBA(0x00, 0xff, 0x00, 0xff), 3, 177, 255);
    sweepClock1_->SetHandLine(UISweepClock::HandType::SECOND_HAND, { 233, 10 }, { 0, 223 }, Color::GetColorFromRGBA(0xff, 0x00, 0x00, 0xff), 1, 223, 255);
    uint16_t sweepClock1realMilliSecond = 40 * 1000;
    sweepClock1_->SetSweepTime12Hour(10, 20, sweepClock1realMilliSecond, true);

    sweepClock1callback_ = new SweepClockCallback(sweepClock1_);
    sweepClock1animator_ = new Animator(sweepClock1callback_, sweepClock1_, 0, true);
    sweepClock1animator_->Start();

    // Add to rootView
    container_->Add(sweepClock1_);
    sweepClock1_->SetVisible(true);
    
    // Add ImageView to App
    if (image1_ == nullptr) {
        image1_ = new UIImageView();
    }
    image1_->SetPosition(0, 0);         // widget's left position and top position
    image1_->Resize(100, 100);          // widget's width and height
    image1_->SetViewId("image1");// Set style

    // Set additional property
#ifdef _WIN32
    char* image1imagesPath = "c:/Users/caiking/project/image_converter_tool/dogmalio.bin";
#else
    char* image1imagesPath = "/user/res/dogmalio.bin";
#endif
    image1_->SetSrc(image1imagesPath);

    // Add to rootView
    container_->Add(image1_);
    image1_->SetVisible(true);
    
}

void MainView::DeInit()
{
    if (container_ != nullptr) {
        container_->RemoveAll();
        delete container_ ;
        container_ = nullptr;
    }
    if (radioButton1_ != nullptr) {
        delete radioButton1_;
        radioButton1_ = nullptr;
    }
    if (button1_ != nullptr) {
        delete button1_;
        button1_ = nullptr;
    }
    if (uiChart1_ != nullptr) {
        delete uiChart1_;
        uiChart1_ = nullptr;
    }if (list1_ != nullptr) {
        delete list1_;
        list1_ = nullptr;
    }
    if (list1adapter_ != nullptr) {
        delete list1adapter_;
        list1adapter_ = nullptr;
    }
    if (list1data_ != nullptr) {
        list1data_->Clear();
        delete list1data_;
        list1data_ = nullptr;
    }
    if (digitalClock1_ != nullptr) {
        delete digitalClock1_;
        digitalClock1_ = nullptr;
    }
    if (slider1_ != nullptr) {
        delete slider1_;
        slider1_ = nullptr;
    }
    if (image2_ != nullptr) {
        delete image2_;
        image2_ = nullptr;
    }
    if (analogClock1callback_ != nullptr) {
        delete analogClock1callback_;
        analogClock1callback_ = nullptr;
    }
    if (analogClock1animator_ != nullptr) {
        delete analogClock1animator_;
        analogClock1animator_ = nullptr;
    }
    if (sweepClock1callback_ != nullptr) {
        delete sweepClock1callback_;
        sweepClock1callback_ = nullptr;
    }
    if (sweepClock1animator_ != nullptr) {
        delete sweepClock1animator_;
        sweepClock1animator_ = nullptr;
    }
    if (image1_ != nullptr) {
        delete image1_;
        image1_ = nullptr;
    }
}

UIView* MainView::GetView()
{
    Init();
    return container_;
}

}